package com.pig4cloud.pig.module.api.nsh;

import com.pig4cloud.pig.common.core.util.DateUtils;
import com.pig4cloud.pig.module.api.entity.platform.PlatformPay;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * @author kkqiao0
 * 全民付移动支付小程序支付订单交易查询接口
 * 说明：
 * 钱包支付时，因通讯故障、服务器故障等原因，造成收银机最终没有收到支付结果通知，收银员不确定
 * 该笔支付后台处理结果，可以在收银机上发起“查询”交易，查询该笔交易订单在钱包后台的支付结果，
 * 并将支付结果返回给收银机。
 *  测试环境：http://58.247.0.18:29015/v1/netpay/query
 *  生产环境：https://api-mop.chinaums.com/v1/netpay/query
 */
public class NSQuery {

//    static String appid = "银商提供";
//    static String appkey = "银商提供";
//    static String url = "https://test-api-open.chinaums.com/v1/netpay/query";

    public static void main(String[] args) throws Exception{
        //1. 组建请求报文
//        QueryBody reqBody = new QueryBody();
//        reqBody.requestTimestamp = "2019-08-09 17:32:55";
//        reqBody.mid = "898460107420248";
//        reqBody.tid = "00000001";
//        reqBody.instMid = "MINIDEFAULT";
//        reqBody.merOrderId = "101771305dc89764b477474";
//        System.out.println("request body:\n"+reqBody);
//
//        //2. 获取认证报文，timestamp为当前日期，老旧日期无法请求成功
//        String authorization = getAuthorization(appid,appkey,"20190809173200","nonce",reqBody.toString());
//        System.out.println("authorization:\n"+authorization);
//
//        //3. 发送http请求，并解析返回信息
//        String response = request(url,authorization,reqBody.toString());
//        System.out.println("response:\n"+response);
    }

    public static String queryOrder(String out_trade_no, PlatformPay platformPay) throws Exception{
        //1. 组建请求报文
        QueryBody reqBody = new QueryBody();
        reqBody.requestTimestamp = DateUtils.getTime();
        reqBody.mid = platformPay.getMerNo();
        reqBody.tid = platformPay.getTerminalNo();
        reqBody.instMid = "MINIDEFAULT";
        reqBody.merOrderId = out_trade_no;
        System.out.println("request body:\n"+reqBody);

        String timestamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());   // eg:20190227113148
        String nonce = UUID.randomUUID().toString().replace("-", ""); // eg:be46cd581c9f46ecbd71b9858311ea12

        String url = "https://api-mop.chinaums.com/v1/netpay/query";

        //2. 获取认证报文，timestamp为当前日期，老旧日期无法请求成功
        String authorization = getAuthorization(platformPay.getOpenId(),platformPay.getOpenKey(),timestamp,nonce,reqBody.toString());
        System.out.println("authorization:\n"+authorization);

        //3. 发送http请求，并解析返回信息
        String response = request(url,authorization,reqBody.toString());
        System.out.println("订单查询返回 : \n"+response);
        return response;
    }

    /**
     * 发送http请求
     * @param url 请求url
     * @param authorization 认证报文
     * @param reqBody  请求体
     * @return response
     */
    static String request(String url, String authorization, String reqBody){
        String response = "";
        PrintWriter out = null;
        BufferedReader in = null;
        try{
            URL realUrl = new URL(url);
            URLConnection conn = realUrl.openConnection();
            HttpURLConnection httpUrlConnection = (HttpURLConnection) conn;
            httpUrlConnection.setRequestProperty("Content-Type", "application/json");
            httpUrlConnection.setRequestProperty("authorization",authorization);
            httpUrlConnection.setDoOutput(true);
            httpUrlConnection.setDoInput(true);
            out = new PrintWriter(httpUrlConnection.getOutputStream());
            out.write(reqBody);
            out.flush();
            httpUrlConnection.connect();
            in = new BufferedReader(new InputStreamReader(httpUrlConnection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                response += line;
            }
        }catch(Exception e){
            e.printStackTrace();
        } finally {
            try {
                if (out != null) { out.close();}
                if (in != null) {in.close();}
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        return response;
    }

    /**
     * 获取签名头
     * @param appid
     * @param appkey
     * @param timestamp 格式:"yyyyMMddHHmmss"
     * @param nonce 随机字符串，
     * @param body 请求体
     * @return authorization 认证报文
     * @throws Exception
     */
    static String getAuthorization(String appid, String appkey, String timestamp, String nonce, String body) throws Exception {
        byte[] data = body.getBytes(StandardCharsets.UTF_8);
        InputStream is = new ByteArrayInputStream(data);
        String testSH = DigestUtils.sha256Hex(is);
        String s1 = appid+timestamp+nonce+testSH;
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(appkey.getBytes(StandardCharsets.UTF_8),"HmacSHA256"));
        byte[] localSignature = mac.doFinal(s1.getBytes(StandardCharsets.UTF_8));
        String localSignatureStr = Base64.encodeBase64String(localSignature);
        return  "OPEN-BODY-SIG AppId="+"\""+appid+"\""+", Timestamp="+"\""+timestamp+"\""+", Nonce="+"\""+nonce+"\""+", Signature="+"\""+localSignatureStr+"\"";
    }

    static class QueryBody{
        //消息ID
        String msgId;
        //报文请求时间，格式yyyy-MM-ddHH:mm:ss
        String requestTimestamp;
        //请求系统预留字段
        String srcReserve;
        //商户号
        String mid;
        //终端号
        String tid;
        //业务类型
        String instMid;
        //商户订单号
        String merOrderId;

        String toJson(){
            StringBuilder sb = new StringBuilder();
            sb.append("{");
            if (this.msgId != null) sb.append("\"msgId\":\"" + this.msgId + "\",");
            if (this.requestTimestamp != null) sb.append("\"requestTimestamp\":\"" + this.requestTimestamp + "\",");
            if (this.srcReserve != null) sb.append("\"srcReserve\":\"" + this.srcReserve + "\",");
            if (this.mid != null) sb.append("\"mid\":\"" + this.mid + "\",");
            if (this.tid != null) sb.append("\"tid\":\"" + this.tid + "\",");
            if (this.instMid != null) sb.append("\"instMid\":\"" + this.instMid + "\",");
            if (this.merOrderId != null) sb.append("\"merOrderId\":\"" + this.merOrderId + "\",");
            if (sb.charAt(sb.length() - 1) == ',')
                sb.deleteCharAt(sb.length() - 1);
            sb.append("}");
            return sb.toString();
        }

        public String toString(){
            return this.toJson();
        }

    }

}
